package gov.nist.applet.phone.security;

/**
 * DES算法为密码体制中的对称密码体制，又被成为美国数据加密标准 ，是1972年美国IBM 公司研制的对称密码体制加密算法。
 * 其密钥长度为56位，明文按64位进行分组，将分组后的明文组和56位的密钥按位替代或交换的方法形成密文组的加密方法。

DES加密算法特点：分组比较短、密钥太短、密码生命周期短、运算速度较慢。

DES工作的基本原理是，其入口参数有三个:key、data、mode。 key为加密解密使用的密钥 ，data为加密解密的数据，
mode为其工作模式。当模式为加密模式时，明文按照64DES加密算法位进行分组，形成明文组，key用于对数据加密，当模式为
解密模式时，key用于对数据解密。实际运用中，密钥只用到了64位中的56位，这样才具有高的安全性。

DES( Data Encryption Standard)算法，于1977年得到美国政府的正式许可，是一种用56位密钥来加密64
数据的方法。虽然56位密钥的DES算法已经风光不在,而 且常有用Des加密的明文被破译的报道,但是了解一下昔日美国的标准
加密算法总是有益的,而且目前DES算法得到了广泛的应用,在某些场合,仍然发挥着余 热。
 */
import java.io.File;
import java.io.FileInputStream;  
import java.io.FileOutputStream;  
import java.io.InputStream;  
import java.io.OutputStream;  
import java.security.Key;  
import java.security.SecureRandom;  
import java.util.Vector;
   
import javax.crypto.Cipher;  
import javax.crypto.CipherInputStream;  
import javax.crypto.CipherOutputStream;  
import javax.crypto.KeyGenerator;  
   
import sun.misc.BASE64Decoder;  
import sun.misc.BASE64Encoder;  
   
public class DESEncoder
{ 
	    Key key ;  
	   
	    public DESEncoder() {  
	   
	    }  
	   
	    public DESEncoder(String str) {  
	       setKey(str); // 生成密匙  
	    }  
	   
	    public Key getKey() {  
	       return key ;  
	    }  
	   
	    public void setKey(Key key) {  
	       this . key = key;  
	    }  
	   
	    /** 
	      * 根据参数生成 KEY 
	      */  
	    public void setKey(String strKey) {  
	       try {  
	           KeyGenerator _generator = KeyGenerator.getInstance ( "DES" );  
	           _generator.init( new SecureRandom(strKey.getBytes()));  
	           this . key = _generator.generateKey();  
	           _generator = null ;  
	       } catch (Exception e) {  
	           throw new RuntimeException(  
	                  "Error initializing SqlMap class. Cause: " + e);  
	       }  
	    }  
	   
	    /** 
	      * 加密 String 明文输入 ,String 密文输出 
	      */  
	    public String encryptStr(String strMing) {  
	       byte [] byteMi = null ;  
	       byte [] byteMing = null ;  
	       String strMi = "" ;  
	       BASE64Encoder base64en = new BASE64Encoder();  
	       try {  
	           byteMing = strMing.getBytes( "UTF8" );  
	           byteMi = this .encryptByte(byteMing);  
	           strMi = base64en.encode(byteMi);  
	       } catch (Exception e) {  
	           throw new RuntimeException(  
	                  "Error initializing SqlMap class. Cause: " + e);  
	       } finally {  
	           base64en = null ;  
	           byteMing = null ;  
	           byteMi = null ;  
	       }  
	       return strMi;  
	    }  
	   
	    /** 
	      * 解密 以 String 密文输入 ,String 明文输出 
	      * 
	      * @param strMi 
	      * @return 
	      */  
	    public String decryptStr(String strMi) {  
	       BASE64Decoder base64De = new BASE64Decoder();  
	       byte [] byteMing = null ;  
	       byte [] byteMi = null ;  
	       String strMing = "" ;  
	       try {  
	           byteMi = base64De.decodeBuffer(strMi);  
	           byteMing = this .decryptByte(byteMi);  
	           strMing = new String(byteMing, "UTF8" );  
	       } catch (Exception e) {  
	           throw new RuntimeException(  
	                  "Error initializing SqlMap class. Cause: " + e);  
	       } finally {  
	           base64De = null ;  
	           byteMing = null ;  
	           byteMi = null ;  
	       }  
	       return strMing;  
	    }  
	   
	    /** 
	      * 加密以 byte[] 明文输入 ,byte[] 密文输出 
	      * 
	      * @param byteS 
	      * @return 
	      */  
	    private byte [] encryptByte( byte [] byteS) {  
	       byte [] byteFina = null ;  
	       Cipher cipher;  
	       try {  
	           cipher = Cipher.getInstance ( "DES" );  
	           cipher.init(Cipher. ENCRYPT_MODE , key );  
	           byteFina = cipher.doFinal(byteS);  
	       } catch (Exception e) {  
	           throw new RuntimeException(  
	                  "Error initializing SqlMap class. Cause: " + e);  
	       } finally {  
	           cipher = null ;  
	       }  
	       return byteFina;  
	    }  
	   
	    /** 
	      * 解密以 byte[] 密文输入 , 以 byte[] 明文输出 
	      * 
	      * @param byteD 
	      * @return 
	      */  
	    private byte [] decryptByte( byte [] byteD) {  
	       Cipher cipher;  
	       byte [] byteFina = null ;  
	       try {  
	           cipher = Cipher.getInstance ( "DES" );  
	           cipher.init(Cipher. DECRYPT_MODE , key );  
	           byteFina = cipher.doFinal(byteD);  
	       } catch (Exception e) {  
	           throw new RuntimeException(  
	                  "Error initializing SqlMap class. Cause: " + e);  
	       } finally {  
	           cipher = null ;  
	       }  
	       return byteFina;  
	    }  
	   
	    /** 
	      * 文件 file 进行加密并保存目标文件 destFile 中 
	      * 
	      * @param file 
	      *             要加密的文件 如 c:/test/srcFile.txt 
	      * @param destFile 
	      *             加密后存放的文件名 如 c:/ 加密后文件 .txt 
	      */  
	    public void encryptFile(String file, String destFile) throws Exception {  
	       Cipher cipher = Cipher.getInstance ( "DES" );  
	       // cipher.init(Cipher.ENCRYPT_MODE, getKey());  
	       cipher.init(Cipher. ENCRYPT_MODE , this . key );  
	       InputStream is = new FileInputStream(file);  
	       OutputStream out = new FileOutputStream(destFile);  
	       CipherInputStream cis = new CipherInputStream(is, cipher);  
	       byte [] buffer = new byte [1024];  
	       int r;  
	       while ((r = cis.read(buffer)) > 0) {  
	           out.write(buffer, 0, r);  
	       }  
	       cis.close();  
	       is.close();  
	       out.close();  
	    }  
	   
	    /** 
	      * 文件采用 DES 算法解密文件 
	      * 
	      * @param file 
	      *             已加密的文件 如 c:/ 加密后文件 .txt * 
	      * @param destFile 
	      *             解密后存放的文件名 如 c:/ test/ 解密后文件 .txt 
	      */  
	    public void decryptFile(String file, String dest) throws Exception {  
	       Cipher cipher = Cipher.getInstance ( "DES" );  
	       cipher.init(Cipher. DECRYPT_MODE , this . key );  
	       InputStream is = new FileInputStream(file);  
	       OutputStream out = new FileOutputStream(dest);  
	       CipherOutputStream cos = new CipherOutputStream(out, cipher);  
	       byte [] buffer = new byte [1024];  
	       int r;  
	       while ((r = is.read(buffer)) >= 0) {  
	           cos.write(buffer, 0, r);  
	       }  
	       cos.close();  
	       out.close();  
	       is.close();  
	    } 
	    
	    /**
	     * 加密文件夹，里面可能包括文件或者文件夹
	     * @param file-you want to encrypt 
	     * @param dest-the position you want to save
	     * @throws Exception
	     */
	    public void encrypeFolder(String file,String dest)throws Exception
	    {
	    	File src = new File(file);
	    	File destnation = new File(dest);
	    	
	    	
	    }
	    
		/**
		 * To get a directory's all files.
		 * 
		 * @param sourceFile
		 *            : the source directory
		 * @return the files' collection
		 */
		private Vector<File> getAllFiles(File sourceFile)
		{
			Vector<File> fileVector = new Vector<File>();
			if (sourceFile.isDirectory())
			{
				File[] files = sourceFile.listFiles();
				for (int i = 0; i < files.length; i++)
				{
					fileVector.addAll(getAllFiles(files[i]));
				}
			} else
			{
				fileVector.add(sourceFile);
			}
			return fileVector;
		}
	   
	    public static void main(String[] args) throws Exception {  
	    	DESEncoder des = new DESEncoder( "1234567" );  
	       // DES 加密文件  
	       //des.encryptFile("e:/foo.mov", "d:/encrypt_foo.mov");  
	       // DES 解密文件  
	       // des.decryptFile("G:/ 加密 test.doc", "G:/ 解密 test.doc");  
	       des.decryptFile("d:/encrypt_foo.mov", "e:/decrypt_foo.mov");
	       String str1 = " 要加密的字符串 test" ;  
	       // DES 加密字符串  
	       String str2 = des.encryptStr(str1);  
	       // DES 解密字符串  
	       String deStr = des.decryptStr(str2);  
	       System. out .println( " 加密前： " + str1);  
	       System. out .println( " 加密后： " + str2);  
	       System. out .println( " 解密后： " + deStr);  
	    }  
	}   

